<?php
/**
 * Date: 2023/12/04
 * Time: 16:28
 */

namespace Xtsb\Cims\Http;

use Xtsb\Cims\Exception\ApiErrorDesc;
use Xtsb\Cims\Exception\ApiException;
use think\facade\Log;

class Http
{

  private $host = 'http://cims.my';//localhost

  protected static $instance;

  /**
   * 服务名称
   * @var
   */
  protected static $microservice;

  /**
   * 请求方法
   * @var
   */
  protected $method = 'post';

//  public function __construct($host = '')
//  {
//    $this->host = $host . '/api/V1/';
//  }

  public function __construct()
  {

  }

  public function __clone()
  {

  }

  public static function microservice($microservice)
  {
    self::$microservice = $microservice;

    if (!self::$instance) {
      self::$instance = new self();
    }

    return self::$instance;
  }

  /**
   * Notes:请求方法
   */
  public function method($method)
  {
    $this->method = $method;
    return $this;
  }

  private function host()
  {
    $hostEnv = env('local');
    if ($hostEnv) {
      $this->host = 'http://cims-dev.chetell.com:9000';
    } else {
      $this->host = 'http://cims-request';
    }

    $this->host .= '/' . self::$microservice;

    return $this->host . '/api/v1';
  }

  public function request($api, array $data)
  {
    $request = app('request');
    $postUrl = $this->host() . '/' . $api;

    if (in_array($this->method, ['PUT', 'DELETE'])) {
      $postUrl .= '/' . $data['id'] ?? 0;
    }

//    $userToken = base64_encode(json_encode($request->userInfo));
    $userToken = base64_encode(json_encode([
      'user_info' => $request->userInfo,
      'rules' => $request->rules,
      'route' => ['controller' => $request->controllerName, 'action' => $request->actionName, 'module' => $request->moduleName,]
    ]));

//    $userToken = $request->header('token');
    $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    Log::channel('cims')->info('数据提交 | ' . $this->method . ' ' . $postUrl . '：{data}', ['data' => $data]);

    $ch = curl_init();//初始化curl
    curl_setopt($ch, CURLOPT_URL, $postUrl);//抓取指定网页
//    curl_setopt($ch, CURLOPT_PROXY, 1);//抓取指定网页
    curl_setopt($ch, CURLOPT_HEADER, 0);//表示需要response header
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
//        'Content-Type: application/x-www-data-urlencoded; charset=utf-8',
        'Content-Type: application/json; charset=utf-8',
//        'Content-Type: multipart/form-data; charset=utf-8',//文件
        'token: ' . $request->header('token'),
        'user-token: ' . $userToken,
//        'user-rules: ' . base64_encode(json_encode($request->rules)),
        'Http-User-Agent: ' . $request->httpUserAgent,
      ]
    );

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//将结果返回，不输出任何内容
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);//请求过期时间
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);//提交方式

    curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//这里的http_build_query()函数就是用来处理curl_post传输多维数组的
    //忽略证书
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//    dump(curl_getinfo($ch));
    $result = curl_exec($ch);//运行curl
    $error = curl_error($ch);
    curl_close($ch);
//    dd($result);
//    dd($result, $error);
    $errorMsg = '请求成功';
    if ($error) {
      $errorMsg = '请求失败 ' . $error;
//      Log::channel('cims')->info('数据返回 失败 | ' . $this->method . ' ' . $postUrl . '：{data}', ['data' => self::$microservice . ' 请求错误 ' . $error]);
//
//      throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, $error);
    }

    if (is_bool($result)) {
      $errorMsg = '请求失败 返回格式错误 ' . $error;
//      Log::channel('cims')->info('数据返回 失败 | ' . $this->method . ' ' . $postUrl . '：{data}', ['data' => self::$microservice . ' 返回格式错误 ']);
//
//      throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, self::$microservice . ' 返回格式错误 ');
    }

    if (json_decode($result)) {
//      Log::channel('cims')->info('数据返回 成功 | ' . $this->method . ' ' . $postUrl . '：{data}', ['data' => $result]);

    } else {
      $errorMsg = '请求失败 ' . $result;

//      echo $result;
//      Log::channel('cims')->info('数据返回 失败 | ' . $this->method . ' ' . $postUrl . '：{data}', ['data' => self::$microservice . ' 请求错误' . $result]);
//
//      throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, self::$microservice . ' 请求错误<br/>' . $result);
    }

    $headers = $request->header();
    unset($headers['user-token']);
    $logInfo = [
      "{$errorMsg} {$this->method} {$postUrl}",
      '[ ROUTE ] ' . var_export(self::getRouteInfo(), true),
      '[ HEADER ] ' . var_export($headers, true),
      '[ USER ] ' . var_export($userToken, true),
      '[ PARAM ] ' . var_export($data, true),
      '---------------------------------------------------------------',
    ];

    $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
    \think\facade\Log::channel('cims')->info($logInfo);

    unset($headers, $logInfo, $data);

    return $result;
  }

  /**
   * 获取路由信息
   * @return array
   */
  private static function getRouteInfo(): array
  {
    $request = app('request');
    return [
      'rule' => $request->rule()->getRule(),
      'route' => $request->rule()->getRoute(),
      'option' => $request->rule()->getOption(),
      'var' => $request->rule()->getVars(),
    ];
  }

  public function get($url = '', $code = 'utf-8')
  {
    $ch = curl_init();
    $timeout = 30;

//    header('User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36');
    curl_setopt($ch, CURLOPT_URL, $this->host . $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_HTTPGET, true);
    $result = curl_exec($ch);
    curl_close($ch);
    if ($code == 'gb2312') {
      $result = mb_convert_encoding($result, "utf-8", "gb2312"); // 编码转换，否则乱码
    }

    return json_decode($result, true);
  }

  public function post($api, array $data)
  {
    $request = app('request');
    $postUrl = self::$host . $api;

    $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    Log::channel('cims')->info('数据提交 | POST ' . $postUrl . '：{data}', ['data' => $data]);

    $ch = curl_init();//初始化curl
    curl_setopt($ch, CURLOPT_URL, $postUrl);//抓取指定网页
    curl_setopt($ch, CURLOPT_HEADER, 0);//表示需要response header
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
//        'Content-Type: application/x-www-data-urlencoded; charset=utf-8',
        'Content-Type: application/json; charset=utf-8',
//        'Content-Type: multipart/form-data; charset=utf-8',//文件
        'token: ' . $request->header('token'),
      )
    );

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);//请求过期时间
    curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
//    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");//POST提交方式
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//这里的http_build_query()函数就是用来处理curl_post传输多维数组的
    //忽略证书
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $result = curl_exec($ch);//运行curl
    $error = curl_error($ch);

    curl_close($ch);

    $res = json_decode($result, true);

    if ($res) {

      Log::channel('cims')->info('数据返回 成功 | ' . $postUrl . '：{data}', ['data' => $result]);

      if (isset($res['code'])) {

        switch ($res['code']) {
          case 404:
            throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, $res['message'] . '：[' . $postUrl . ']');
            break;
          case 0:
            return $res['data'];
            break;
          default:
            throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, $res['message'] ?? '网络错误');
            break;
        }
      } else {
        throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, $res['message'] ?? '网络错误');
      }

    } else {

      Log::channel('cims')->info('数据返回 失败 | ' . $postUrl . '：{data}', ['data' => $result]);

      dd($result);
    }


  }

  /**
   * 暂时不用
   * @param $api
   * @param $data
   * @return bool|string|void
   */
  public function put($api, array $data)
  {
    $request = app('request');
    $postUrl = $this->host . $api;

    $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    Log::channel('cims')->info('数据提交 | ' . $postUrl . '：{data}', ['data' => $data]);

    $ch = curl_init();//初始化curl
    curl_setopt($ch, CURLOPT_URL, $postUrl);//抓取指定网页
    curl_setopt($ch, CURLOPT_HEADER, 0);//表示需要response header
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
//        'Content-Type: application/x-www-data-urlencoded; charset=utf-8',
        'Content-Type: application/json; charset=utf-8',
//        'Content-Type: multipart/form-data; charset=utf-8',//文件
        'token: ' . $request->header('token'),
      )
    );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);//请求过期时间
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");//put提交方式
    //curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//这里的http_build_query()函数就是用来处理curl_post传输多维数组的
    //忽略证书
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $result = curl_exec($ch);//运行curl
    $error = curl_error($ch);

    curl_close($ch);


    if (json_decode($result)) {

      Log::channel('cims')->info('数据返回 成功 | ' . $postUrl . '：{data}', ['data' => $result]);

      return json_decode($result, true);

    } else {

      Log::channel('cims')->info('数据返回 失败 | ' . $postUrl . '：{data}', ['data' => $result]);
      exit($result);
      return $result;
    }

  }


  /**
   * 暂时不用
   * @param $api
   * @param $data
   * @return bool|string|void
   */
  public function delete($api, array $data)
  {
    $request = app('request');
    $postUrl = $this->host . $api . '/' . $data['id'] ?? 0;

    $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    Log::channel('cims')->info('数据提交 | ' . $postUrl . '：{data}', ['data' => $data]);

    $ch = curl_init();//初始化curl
    curl_setopt($ch, CURLOPT_URL, $postUrl);//抓取指定网页
    curl_setopt($ch, CURLOPT_HEADER, 0);//表示需要response header
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
//        'Content-Type: application/x-www-data-urlencoded; charset=utf-8',
        'Content-Type: application/json; charset=utf-8',
//        'Content-Type: multipart/form-data; charset=utf-8',//文件
        'token: ' . $request->header('token'),
      )
    );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);//请求过期时间
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");//delete提交方式
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//这里的http_build_query()函数就是用来处理curl_post传输多维数组的
    //忽略证书
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

    $result = curl_exec($ch);//运行curl
    $error = curl_error($ch);

    curl_close($ch);


    if (json_decode($result)) {

      Log::channel('cims')->info('数据返回 成功 | ' . $postUrl . '：{data}', ['data' => $result]);

      return json_decode($result, true);

    } else {
      dd(111111);
      Log::channel('cims')->info('数据返回 失败 | ' . $postUrl . '：{data}', ['data' => $result]);

//      throw new ApiException(ApiErrorDesc::ERROR_DEFAULT, $result);
//    catch();
//      dd(json_decode($result));
      dd(0, $result, $error);
      return $result;
    }

  }
}
